#include "config.h"

#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#define DBG_SUBSYS S_LIBSTORAGE

#include "yid.h"
#include "dbg.h"
#include "volume_proto.h"

#include "lsv_volume_storage.h"

int lsv_low_storage_lich_write(lsv_volume_proto_t *lsv_info, int8_t *_buf, lsv_u8_t type, lsv_u64_t offset, lsv_u32_t size)
{
        int ret;
        volume_proto_t *volume_proto = NULL;
        io_opt_t io_opt;
        io_t io;
        buffer_t buf;
        volume_proto = lsv_info->volume_proto;

        // @malloc ERR1
        mbuffer_init(&buf, 0);
        mbuffer_attach(&buf, _buf, size, NULL);

        // 0: ssd, 1: hdd, -1: auto tier，不启用
        int priority = (type == LSV_STORAGE_TYPE_SSD) ? 0: 1;
        io_opt_init(&io_opt, 0, priority, 0, IO_OPT_SET_PRIORITY);

        DINFO("chunk_id %ju type %d priority %d\n", offset/1048576, type, priority);

        // 需要写入SSD的数据，不经过SSD cache
        io_init(&io, &volume_proto->chkid, NULL, offset, size, (type == LSV_STORAGE_TYPE_SSD) ? __FILE_ATTR_DIRECT__ : 0);

        ret = volume_proto_write_raw(volume_proto, &io_opt, &io, &buf);
        if (unlikely(ret)) {
                GOTO(ERR1, ret);
        }

        offset =  (offset + size + 1073741824) / 1073741824 * 1073741824;
        offset -= size;
        ret = volume_proto_truncate(volume_proto, offset, size);
        if (unlikely(ret)) {
                GOTO(ERR1, ret);
        }

        mbuffer_free(&buf);

        return 0;
ERR1:
        mbuffer_free(&buf);

        DFATAL("%s ret %d off %ju size %u\n", strerror(ret), ret, offset, size);
        ret = _errno(ret);
        return ret;
}

int lsv_low_storage_lich_read(lsv_volume_proto_t *lsv_info, uint64_t offset, uint32_t size, int8_t *_buf)
{
        int ret;
        volume_proto_t *volume_proto = NULL;
        io_t io;
        buffer_t buf;
        volume_proto = lsv_info->volume_proto;

        // @malloc ERR1
        mbuffer_init(&buf, 0);

        io_init(&io, &volume_proto->chkid, NULL, offset, size, 0);

        ret = volume_proto_read_raw(volume_proto, &io, &buf);
        if (unlikely(ret)) {
                GOTO(ERR1, ret);
        }

        size = buf.len;
        mbuffer_get(&buf, _buf, size);

        mbuffer_free(&buf);

        return 0;
ERR1:
        mbuffer_free(&buf);

        DFATAL("%s ret %d off %ju size %u\n", strerror(ret), ret, offset, size);
        ret = _errno(ret);

        return ret;
}